當我們透過Entity framework 查詢或異動DB的資料時,
會將資料暫存至DbContext快取中,可在後續針對同一個資料表的異動中進行資料比對,
但在部分語法僅做查詢,不會異動到DB的資料時,
DbContext快取可能會存取過多非必要的資料,造成效能上的問題。
若想要讓程式忽略特定的查詢結果時,
可以使用AsNoTracking()方法,讓該查詢不被快取,
這樣就能夠減少資源損耗,進而提升處理效能。
以下程式碼僅針對DB做查詢,由於沒有任何異動,
故針對這個部分做追蹤其實是增加額外的資源負擔:
var employee1 = context.Employees.Where(e => e.Catalog == 1).FirstOrDefault();
return employee1;
在不需要追蹤的部分加入AsNoTracking()後,
對改善查詢速度有很大的幫助:
var employee1 = context.Employees.AsNoTracking().Where(e => e.Catalog == 1).FirstOrDefault();
return employee1;
================================================
一般在使用AsNoTracking()後異動的資料,無法透過SaveChanges()做修改,
因為SaveChanges()也是根據快取的資料去和DB資料做比對,
若資料在有異動的情況下仍想使用AsNoTracking(),
可以使用context.Entry(),變更部分資料的實體狀態,
但僅適合少部分欄位需要變更,其餘資料仍不追蹤時使用:
using (var context = new MyDbContext())
{
var employee1 = context.Employees.AsNoTracking().Where(e => e.Catalog == 1).FirstOrDefault();
employee1.Email = "test@aa.bb.cc";
context.Entry(employee1).State = EntityState.Modified;
context.SaveChanges();
}
參考資料:
使用 AsNoTracking
Entity Framework .AsNoTracking() – why & how (EF and EF Core)
使用實體狀態